import Database from 'better-sqlite3';
import path from 'path';
import fs from 'fs';
import {DbInitializer} from './DbInitializer';
import {getIdGenerator} from '../common';
import {DatabaseOptions, EntityClass, IdGenerationStrategy, IdGenerator, LogicalDeleteConfig, PrimaryKeyConfig} from "../types";
import {FieldFillerManager} from './FieldFillerManager';
import {DatabaseEncryptionManager} from './DatabaseEncryptionManager';

// 默认数据库名称
export const DEFAULT_DB_NAME = 'default';

// 默认列类型
export const DEFAULT_COLUMN_TYPE = 'TEXT';

// 默认主键配置
export const DEFAULT_PRIMARY_KEY_CONFIG: PrimaryKeyConfig = {
  autoGenerateId: true,
  idGenerationStrategy: IdGenerationStrategy.AUTO_INCREMENT
};

// 默认逻辑删除值
export const DEFAULT_LOGICAL_DELETED_VALUE = 1;    // 数值类型，对应 INTEGER 字段类型
export const DEFAULT_LOGICAL_NOT_DELETED_VALUE = 0; // 数值类型，对应 INTEGER 字段类型

// 默认逻辑删除配置
export const DEFAULT_LOGICAL_DELETE_CONFIG: LogicalDeleteConfig = {
  deletedField: 'deleted',
  deletedValue: DEFAULT_LOGICAL_DELETED_VALUE,
  notDeletedValue: DEFAULT_LOGICAL_NOT_DELETED_VALUE
};

/**
 * 管理SQLite数据库连接
 */
export class DatabaseManager {
  private static instances: Map<string, DatabaseManager> = new Map();
  private db: Database.Database | null = null;
  private dbOptions: DatabaseOptions;
  private _initializer: DbInitializer | null = null;
  private entityClasses: EntityClass[] = [];
  private readonly name: string;
  private _primaryKeyConfig: PrimaryKeyConfig;
  private _fieldFiller: FieldFillerManager | null = null;
  // 数据库加密管理器实例
  private _encryptionManager: DatabaseEncryptionManager | null = null;
  // 逻辑删除配置
  private _logicalDeleteConfig: LogicalDeleteConfig | null = null;
  // 是否启用类型强校验
  private _enableStrictTypeCheck: boolean = false;

  /**
   * 创建一个新的DatabaseManager实例
   * @param options 数据库连接选项
   */
  private constructor(options: DatabaseOptions) {
    // 创建一个不包含密码的配置副本
    const { password, ...safeOptions } = options;
    this.dbOptions = safeOptions;

    this.name = options.name || DEFAULT_DB_NAME;
    // 初始化主键配置
    this._primaryKeyConfig = {
      ...DEFAULT_PRIMARY_KEY_CONFIG,
      ...options.primaryKeyConfig
    };

    // 初始化逻辑删除配置，如果启用了此功能
    if (options.logicalDelete) {
      this._logicalDeleteConfig = {
        ...DEFAULT_LOGICAL_DELETE_CONFIG,
        ...options.logicalDelete
      };
    }

    // 设置类型强校验
    this._enableStrictTypeCheck = options.enableStrictTypeCheck || false;

    this.ensureDatabaseDirectory();

    // 如果启用了加密，先初始化加密管理器
    if (options.enableEncryption) {
      this._encryptionManager = new DatabaseEncryptionManager(this);
    }

    // 使用临时变量传递密码，然后初始化
    this.init(password);

    // 如果提供了实体类列表，保存它们
    if (options.entities && Array.isArray(options.entities)) {
      this.entityClasses = [...options.entities];
    }
  }

  /**
   * 获取或创建一个DatabaseManager实例
   * @param options 数据库连接选项
   * @returns DatabaseManager实例
   */
  public static getInstance(options: DatabaseOptions): DatabaseManager {
    const name = options.name || DEFAULT_DB_NAME;

    // 如果启用了加密但未安装加密支持库，抛出错误
    if (options.enableEncryption && !DatabaseEncryptionManager.isEncryptionSupported()) {
      throw new Error('加密功能需要安装better-sqlite3-multiple-ciphers库');
    }

    if (!DatabaseManager.instances.has(name)) {
      DatabaseManager.instances.set(name, new DatabaseManager(options));
    }
    return DatabaseManager.instances.get(name)!;
  }

  /**
   * 通过名称获取DatabaseManager实例
   * @param name 数据库名称，默认为'default'
   * @returns DatabaseManager实例，如果不存在则返回null
   */
  public static getInstanceByName(name: string = DEFAULT_DB_NAME): DatabaseManager | null {
    // 查找具有指定名称的数据库实例
    return DatabaseManager.instances.get(name) || null;
  }

  /**
   * 获取数据库选项
   * @returns 数据库选项
   */
  public getOptions(): DatabaseOptions {
    return this.dbOptions;
  }

  /**
   * 确保数据库目录存在
   */
  private ensureDatabaseDirectory(): void {
    const dbDir = path.dirname(this.dbOptions.dbPath);
    if (!fs.existsSync(dbDir)) {
      fs.mkdirSync(dbDir, {recursive: true});
    }
  }

  /**
   * 初始化数据库连接
   * @param password 数据库密码（临时传递，不保存）
   */
  private init(password?: string): void {
    try {
      // 加载适当的SQLite库
      const SQLite = this.dbOptions.enableEncryption && DatabaseEncryptionManager.isEncryptionSupported()
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        ? require('better-sqlite3-multiple-ciphers')
        : Database;

      // 连接数据库
      this.db = new SQLite(this.dbOptions.dbPath, this.dbOptions.sqliteOptions);

      // 如果启用了加密且提供了密码，设置密码
      if (this.dbOptions.enableEncryption && password) {
        if (this.db && DatabaseEncryptionManager.isEncryptionSupported()) {
          // 使用加密管理器设置密钥
          if (this._encryptionManager) {
            this._encryptionManager.setKey(this.db, password);
            // 在使用后立即清除密码
            password = undefined;
          } else {
            throw new Error('加密管理器初始化失败');
          }
        } else {
          throw new Error('加密功能需要安装better-sqlite3-multiple-ciphers库');
        }
      }

      // 设置pragma以提高性能
      if (this.db && this.dbOptions.enableWAL !== false) {
        this.db.pragma('journal_mode = WAL');
      }

      if (this.db && this.dbOptions.enableForeignKeys !== false) {
        this.db.pragma('foreign_keys = ON');
      }
    } catch (error) {
      console.error('数据库初始化失败:', error);
      this.db = null;
      throw error;
    }
  }

  /**
   * 获取数据库实例
   * @returns SQLite数据库实例
   */
  public getDatabase(): Database.Database {
    if (!this.db) {
      throw new Error('数据库未初始化或已关闭');
    }
    return this.db;
  }

  /**
   * 关闭数据库连接
   */
  public closeDatabase(): void {
    if (this.db) {
      this.db.close();
      this.db = null;

      // 从实例映射中移除
      DatabaseManager.instances.delete(this.name);
    }
  }

  /**
   * 获取数据库文件路径
   * @returns 数据库文件路径
   */
  public getDatabasePath(): string {
    return this.dbOptions.dbPath;
  }

  /**
   * 获取数据库名称
   * @returns 数据库名称
   */
  public getName(): string {
    return this.name;
  }

  /**
   * 获取数据库初始化器实例
   * 该方法返回一个DbInitializer实例，可以用于管理表结构
   * @returns DbInitializer实例
   */
  public get initializer(): DbInitializer {
    if (!this._initializer) {
      this._initializer = new DbInitializer(this.getDatabase(), this.entityClasses);
    }
    return this._initializer;
  }

  /**
   * 注册一个实体类用于初始化表
   * @param entityClass 要注册的实体类
   * @returns DatabaseManager实例，支持链式调用
   */
  public registerEntity(entityClass: EntityClass): DatabaseManager {
    if (!this.entityClasses.includes(entityClass)) {
      this.entityClasses.push(entityClass);
      // 如果initializer已经创建，更新其entityClasses
      if (this._initializer) {
        this._initializer.registerEntity(entityClass);
      }
    }
    return this;
  }

  /**
   * 注册多个实体类用于初始化表
   * @param entityClasses 要注册的实体类数组
   * @returns DatabaseManager实例，支持链式调用
   */
  public registerEntities(entityClasses: EntityClass[]): DatabaseManager {
    for (const entityClass of entityClasses) {
      this.registerEntity(entityClass);
    }
    return this;
  }

  /**
   * 获取数据库加密管理器实例
   * @returns DatabaseEncryptionManager实例
   */
  public get encryption(): DatabaseEncryptionManager {
    if (!this._encryptionManager) {
      this._encryptionManager = new DatabaseEncryptionManager(this);
    }
    return this._encryptionManager;
  }

  /**
   * 便捷方法：初始化数据库表
   * 等同于 dbManager.initializer.initTables(force)
   * @param force 是否强制重新创建表（即使已存在）
   * @returns 创建的表数量
   */
  public initTables(force: boolean = false): number {
    return this.initializer.initTables(force);
  }

  /**
   * 获取数据库的主键配置
   * @returns 主键配置
   */
  public get primaryKeyConfig(): PrimaryKeyConfig {
    return this._primaryKeyConfig;
  }

  /**
   * 设置数据库的主键配置
   * @param config 主键配置
   */
  public setPrimaryKeyConfig(config: Partial<PrimaryKeyConfig>): void {
    this._primaryKeyConfig = {...this._primaryKeyConfig, ...config};
  }

  /**
   * 获取ID生成器
   * @returns 根据配置的生成策略返回ID生成器
   */
  public getIdGenerator(): IdGenerator {
    const {idGenerationStrategy, customIdGenerator, snowflakeNodeId} = this._primaryKeyConfig;
    return getIdGenerator(
      idGenerationStrategy || IdGenerationStrategy.AUTO_INCREMENT,
      customIdGenerator,
      {nodeId: snowflakeNodeId}
    );
  }

  /**
   * 生成一个新的ID
   * 根据配置的生成策略生成ID
   * @returns 生成的ID
   */
  public generateId(): string | number {
    // AUTO_INCREMENT策略不需要手动生成ID
    if (this._primaryKeyConfig.idGenerationStrategy === IdGenerationStrategy.AUTO_INCREMENT) {
      throw new Error('AUTO_INCREMENT策略由SQLite处理，不应手动生成ID');
    }
    return this.getIdGenerator().generate();
  }

  /**
   * 获取字段填充器管理器实例
   * @returns FieldFillerManager实例
   */
  public get fieldFiller(): FieldFillerManager {
    if (!this._fieldFiller) {
      this._fieldFiller = new FieldFillerManager(this);
    }
    return this._fieldFiller;
  }

  /**
   * 获取逻辑删除配置
   * @returns 逻辑删除配置
   */
  public get logicalDeleteConfig(): LogicalDeleteConfig | null {
    return this._logicalDeleteConfig;
  }

  /**
   * 检查是否启用了类型强校验
   * @returns 是否启用了类型强校验
   */
  public isStrictTypeCheckEnabled(): boolean {
    return this._enableStrictTypeCheck;
  }

  /**
   * 设置是否启用类型强校验
   * @param enable 是否启用
   */
  public setStrictTypeCheck(enable: boolean): void {
    this._enableStrictTypeCheck = enable;
  }
}
